/*
 * Copyright (C) 2011 The Android Open Source Project
 * Copyright (C) 2011 Jake Wharton
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.wanhelibs.indicator;

import android.content.Context;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;

import com.wanhe.base.util.ObjectUtil;
import com.wanhelibs.R;

import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;

/**
 * This widget implements the dynamic action bar tab behavior that can change
 * across different configurations or circumstances.
 */
public class TabIndicatorLayout extends HorizontalScrollView {
	private int					mTabViewDefualWidth;
	private BaseAdapter			mAdapter;

	private Runnable			mTabSelector;

	private final LinearLayout	mTabLayout;

	private int					mMaxTabWidth;
	private int					mSelectedTabIndex;

	public interface OnTabItemClickListener {
		void onTabClick(View view, int index);
	}

	/**
	 * 暴露给外部操作的事件监听
	 */
	private OnTabItemClickListener tabItemClickListener;

	public void setTabItemClickListener(OnTabItemClickListener tabItemClickListener) {
		this.tabItemClickListener = tabItemClickListener;
	}

	private OnClickListener clickListener = new OnClickListener() {
		@Override
		public void onClick(View view) {
			TabView tabView = (TabView) view;
			int index = tabView.getIndex();
			setCurrentItem(index);
			if (ObjectUtil.checkObject(tabItemClickListener)) {
				tabItemClickListener.onTabClick(tabView.getChildAt(0), index);
			}
		}
	};

	public TabIndicatorLayout(Context context) {
		this(context, null);
	}

	public TabIndicatorLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		setHorizontalScrollBarEnabled(false);

		TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TabIndicatorLayout);
		mTabViewDefualWidth = a.getDimensionPixelSize(R.styleable.TabIndicatorLayout_tab_def_width,
				-1);
		a.recycle();

		mTabLayout = new LinearLayout(context);
		addView(mTabLayout, new ViewGroup.LayoutParams(WRAP_CONTENT, MATCH_PARENT));
	}

	@Override
	public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
		final boolean lockedExpanded = widthMode == MeasureSpec.EXACTLY;
		setFillViewport(lockedExpanded);

		final int childCount = mTabLayout.getChildCount();
		if (childCount > 1
				&& (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST)) {
			if (childCount > 2) {
				mMaxTabWidth = (int) (MeasureSpec.getSize(widthMeasureSpec) * 0.4f);
			} else {
				mMaxTabWidth = MeasureSpec.getSize(widthMeasureSpec) / 2;
			}
		} else {
			mMaxTabWidth = -1;
		}

		final int oldWidth = getMeasuredWidth();
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		final int newWidth = getMeasuredWidth();

		if (lockedExpanded && oldWidth != newWidth) {
			// Recenter the tab display if we're at a new (scrollable) size.
			setCurrentItem(mSelectedTabIndex);
		}
	}

	private void animateToTab(final int position) {
		final View tabView = mTabLayout.getChildAt(position);
		if (mTabSelector != null) {
			removeCallbacks(mTabSelector);
		}
		mTabSelector = new Runnable() {
			public void run() {
				final int scrollPos = tabView.getLeft() - (getWidth() - tabView.getWidth()) / 2;
				smoothScrollTo(scrollPos, 0);
				mTabSelector = null;
			}
		};
		post(mTabSelector);
	}

	@Override
	public void onAttachedToWindow() {
		super.onAttachedToWindow();
		if (mTabSelector != null) {
			// Re-post the selector we saved
			post(mTabSelector);
		}
	}

	@Override
	public void onDetachedFromWindow() {
		super.onDetachedFromWindow();
		if (mTabSelector != null) {
			removeCallbacks(mTabSelector);
		}
	}

	public void setAdapter(BaseAdapter adapter) {
		this.mAdapter = adapter;
		this.mAdapter.registerDataSetObserver(new DataSetObserver() {
			@Override
			public void onChanged() {
				super.onChanged();
				notifyDataSetChanged();
			}
		});
	}

	public void notifyDataSetChanged() {
		mTabLayout.removeAllViews();
		final int count = mAdapter.getCount();
		for (int i = 0; i < count; i++) {
			addTab(i);
		}
		if (mSelectedTabIndex > count) {
			mSelectedTabIndex = count - 1;
		}
		setCurrentItem(mSelectedTabIndex);
		requestLayout();
	}

	private void addTab(int position) {
		View childView = mAdapter.getView(position, null, null);
		TabView tabView = new TabView(getContext());
		tabView.setOnClickListener(clickListener);
		tabView.mIndex = position;
		tabView.addView(childView, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
		tabView.setGravity(Gravity.CENTER);
		mTabLayout.addView(tabView, new ViewGroup.LayoutParams(WRAP_CONTENT, MATCH_PARENT));
	}

	public void setCurrentItem(int item) {
		mSelectedTabIndex = item;
		final int tabCount = mTabLayout.getChildCount();
		for (int i = 0; i < tabCount; i++) {
			final View child = mTabLayout.getChildAt(i);
			final boolean isSelected = (i == item);
			child.setSelected(isSelected);
			if (isSelected) {
				animateToTab(item);
			}
		}
	}

	public class TabView extends LinearLayout {
		private int mIndex;

		public TabView(Context context) {
			super(context, null);
		}

		@Override
		public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
			super.onMeasure(widthMeasureSpec, heightMeasureSpec);

			if (TabIndicatorLayout.this.mMaxTabWidth > 0
					&& this.getMeasuredWidth() > TabIndicatorLayout.this.mMaxTabWidth) {
				super.onMeasure(
						MeasureSpec.makeMeasureSpec(this.getMeasuredWidth(), MeasureSpec.EXACTLY),
						heightMeasureSpec);
			} else if (this.getMeasuredWidth() <= TabIndicatorLayout.this.mTabViewDefualWidth) {
				super.onMeasure(
						MeasureSpec.makeMeasureSpec(TabIndicatorLayout.this.mTabViewDefualWidth,
								MeasureSpec.EXACTLY),
						heightMeasureSpec);
			}
		}

		public int getIndex() {
			return mIndex;
		}
	}
}
